#include "wm_include.h"
#include "wm_gpio_afsel.h"
#include "codec.h"
#include "audio.h"
#include "../../user_config.h"

static u8 ReadRegister(u16 addr);
static void WriteRegister(u16 addr, u8 data);

void CodecMCLKOut(uint8_t div)
{


#if !CODEC_ALWAYS_AS_MASTER_FTR	
	return;
#endif
    u8 channel = 2;
	tls_pwm_stop(channel);
    wm_pwm2_config(I2S_MCLK);
    // u8 channel = 4;
	// tls_pwm_stop(channel);
    // wm_pwm4_config(I2S_MCLK);
    tls_pwm_out_mode_config(channel, WM_PWM_OUT_MODE_INDPT);
    tls_pwm_cnt_type_config(channel, WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT);
    tls_pwm_freq_config(channel, 0, div - 1);
    tls_pwm_duty_config(channel, (div-1)/2);
    tls_pwm_loop_mode_config(channel, WM_PWM_LOOP_TYPE_LOOP);
    tls_pwm_out_inverse_cmd(channel, DISABLE);
    tls_pwm_output_en_cmd(channel, WM_PWM_OUT_EN_STATE_OUT);
    tls_pwm_start(channel);
}

void CodecSetSampleRate(unsigned int sr)
{
//    uint8_t i = 0;
	static int mclk = 0;
	static int switchflag = 0;
    
   // printf("sr = %d\n", sr);
    switch(sr)
    {
        case 8000:
			if (mclk == 0)
			{
            	CodecMCLKOut(5);
				mclk = 1;
			}
#if CODEC_ALWAYS_AS_MASTER_FTR
			WriteRegister(0x06, 0x18);
#endif
            WriteRegister(0x02, 0x08);
            WriteRegister(0x05, 0x44);
			if (switchflag == 0)
			{
				switchflag = 1;
	            WriteRegister(0x03, 0x19);
	            WriteRegister(0x04, 0x19);
			}
            break;
        case 16000:
			if (mclk == 0)
			{
            	CodecMCLKOut(5);
				mclk = 1;
			}
#if CODEC_ALWAYS_AS_MASTER_FTR
			WriteRegister(0x06, 0x0F);
#endif
            WriteRegister(0x02, 0x90);
            WriteRegister(0x05, 0x00);
			if (switchflag == 0)
			{
				switchflag = 1;
	            WriteRegister(0x03, 0x19);
	            WriteRegister(0x04, 0x19);
			}

            break;
        case 32000:
			if (mclk == 0)
			{
            	CodecMCLKOut(5);
				mclk = 1;
			}

            WriteRegister(0x02, 0x18);
            WriteRegister(0x05, 0x44);
			if (switchflag == 0)
			{
				switchflag = 1;
	            WriteRegister(0x03, 0x19);
	            WriteRegister(0x04, 0x19);
			}

            break;
        case 44100:
			mclk = 0;
			switchflag = 0;
            CodecMCLKOut(28);
            WriteRegister(0x02, (0x03 << 3));
            WriteRegister(0x05, 0x00);
            WriteRegister(0x03, 0x10);
            WriteRegister(0x04, 0x10);
            break;
        case 22050:
			mclk = 0;
			switchflag = 0;

            CodecMCLKOut(28);
            WriteRegister(0x02, (0x02 << 3));
            WriteRegister(0x05, 0x00);
            WriteRegister(0x03, 0x10);
            WriteRegister(0x04, 0x10);
            break;
        case 11025:
			mclk = 0;			
			switchflag = 0;
            CodecMCLKOut(28);
            WriteRegister(0x02, (0x01 << 3));
            WriteRegister(0x05, 0x00);
            WriteRegister(0x03, 0x10);
            WriteRegister(0x04, 0x10);
            break;
        case 48000:
			mclk = 0;		
			switchflag = 0;
            CodecMCLKOut(26);
            WriteRegister(0x02, (0x03 << 3));
            WriteRegister(0x05, 0x00);
            WriteRegister(0x03, 0x10);
            WriteRegister(0x04, 0x10);
            break;
        case 24000:
			mclk = 0;		
			switchflag = 0;
            CodecMCLKOut(26);
            WriteRegister(0x02, (0x02 << 3));
            WriteRegister(0x05, 0x00);
            WriteRegister(0x03, 0x10);
            WriteRegister(0x04, 0x10);
            break;
        case 12000:
			mclk = 0;			
			switchflag = 0;
            CodecMCLKOut(26);
            WriteRegister(0x02, (0x01 << 3));
            WriteRegister(0x05, 0x00);
            WriteRegister(0x03, 0x10);
            WriteRegister(0x04, 0x10);
            break;
        default:
            break;
    }
}

#define ADC_VOLUME_GAIN 0xDF //0xEF
#define DADC_GAIN 0x1A //0x17
#if CODEC_ALWAYS_AS_MASTER_FTR
#define BCLK_DIV  0x0F //0x07
#else
#define BCLK_DIV  0x13 //0x07
#endif
void CodecInit(void)
{
    u8 temp1 = 0, temp2 = 0, temp3 = 0;
//	int i = 0;
#if CODEC_ALWAYS_AS_MASTER_FTR
	CodecMCLKOut(5);
#endif
    wm_i2c_scl_config(CODEC_I2C_SCL);
    wm_i2c_sda_config(CODEC_I2C_SDA);
    tls_i2c_init(I2C_REQ);

    temp1 = ReadRegister(0xFD);
    temp2 = ReadRegister(0xFE);
    temp3 = ReadRegister(0xFF);
    if(temp1 != 0x83 || temp2 != 0x11)
    {
        printf("codec err, id = 0x%x 0x%x ver = 0x%x\n", temp1, temp2, temp3);
        return;
    }
    
   //the sequence for start up codec
    // RESET CODEC
    WriteRegister(0x00, 0x1F);
	//for (i = 0 ; i < 2; i++)
	{
	    WriteRegister(0x45, 0x00);

	    // SET ADC/DAC CLK
	    WriteRegister(0x01, 0x30);
	    WriteRegister(0x02, 0x90);
	    WriteRegister(0x03, 0x19);
	    WriteRegister(0x16, 0x02);// bit5:0~non standard audio clock
	    WriteRegister(0x04, 0x19);
	    WriteRegister(0x05, 0x00);
		/*new cfg*/
		WriteRegister(0x06, BCLK_DIV);
		WriteRegister(0x07, 0x01);
		WriteRegister(0x08, 0xff);

	    // SET SYSTEM POWER UP
	    WriteRegister(0x0B, 0x00);
	    WriteRegister(0x0C, 0x00);
	    WriteRegister(0x10, 0x1F);
	    WriteRegister(0x11, 0x7F);
#if CODEC_ALWAYS_AS_MASTER_FTR	
		WriteRegister(0x00, 0xC0);
#else
		WriteRegister(0x00, 0x80);
#endif
	    tls_os_time_delay(HZ/20);
	    WriteRegister(0x0D, 0x01);
	    WriteRegister(0x01, 0x3F);

	    // SET ADC
	    WriteRegister(0x14, DADC_GAIN);

	    // SET DAC
	    WriteRegister(0x12, 0x00);

	    // ENABLE HP DRIVE
	    WriteRegister(0x13, 0x10);//

	    // SET ADC/DAC DATA FORMAT
	    WriteRegister(0x09, 0x0C);// right channel to dac
	    WriteRegister(0x0A, 0x0C);//
	    

	    // SET LOW OR NORMAL POWER MODE
	    WriteRegister(0x0E, 0x02);
	    WriteRegister(0x0F, 0x44);

	    // SET ADC
	    WriteRegister(0x15, 0x00);
	    WriteRegister(0x1B, 0x05);
	    WriteRegister(0x1C, 0x65);
	    WriteRegister(0x37, 0x08);	
	    WriteRegister(0x17, ADC_VOLUME_GAIN);
	    WriteRegister(0x32, 0xBF);//  DAC VOL
//  		WriteRegister(0x18, 0x87);
 //       WriteRegister(0x19, 0xa5);    
	}
#if 0


    // SET ADC/DAC DATA FORM
    WriteRegister(0x44, 0x08);
    
	
    // ADC ALC FUNCTION FOR AMIC RECORD
    WriteRegister(0x16, 0x02);// bit5:0~non standard audio clock
    WriteRegister(0x17, 0xBF);
    WriteRegister(0x18, 0x87);

    WriteRegister(0x19, 0xa5);
    WriteRegister(0x1A, 0x03);
    WriteRegister(0x1B, 0xEA);

    WriteRegister(0x10, 0x0C);
    WriteRegister(0x11, 0x7B);
    WriteRegister(0x13, 0x00);
    WriteRegister(0x0E, 0x02);
    WriteRegister(0x0F, 0x44);
    WriteRegister(0x1B, 0x05);
    WriteRegister(0x1C, 0x65);
#endif
#if 0

	WriteRegister(0x1C,0x65);//close eq
	WriteRegister(0x1D,0x03);
	WriteRegister(0x1E,0x43);
	WriteRegister(0x1F,0x1F);
	WriteRegister(0x20,0x6C);
	WriteRegister(0x21,0x01);
	WriteRegister(0x22,0x32);
	WriteRegister(0x23,0x9B);
	WriteRegister(0x24,0x4B);
	WriteRegister(0x25,0x29);
	WriteRegister(0x26,0x6D);
	WriteRegister(0x27,0xF9);
	WriteRegister(0x28,0xFF);
	WriteRegister(0x29,0x1F);
	WriteRegister(0x2A,0xF7);
	WriteRegister(0x2B,0xFD);
	WriteRegister(0x2C,0xFF);
	WriteRegister(0x2D,0x22);
	WriteRegister(0x2E,0x4B);
	WriteRegister(0x2F,0x5D);
	WriteRegister(0x30,0x7C);
	WriteRegister(0x1C,0x25);//open eq
#endif

}

void CodecReInit(void)
{    
   //the sequence for start up codec
    // RESET CODEC
    WriteRegister(0x00, 0x1F);

    WriteRegister(0x45, 0x00);

    // SET ADC/DAC CLK
    WriteRegister(0x01, 0x30);
    WriteRegister(0x02, 0x90);
    WriteRegister(0x03, 0x19);
    WriteRegister(0x16, 0x02);// bit5:0~non standard audio clock
    WriteRegister(0x04, 0x19);
    WriteRegister(0x05, 0x00);
	/*new cfg*/
	WriteRegister(0x06, BCLK_DIV);
	WriteRegister(0x07, 0x01);
	WriteRegister(0x08, 0xff);

    // SET SYSTEM POWER UP
    WriteRegister(0x0B, 0x00);
    WriteRegister(0x0C, 0x00);
    WriteRegister(0x10, 0x1F);
    WriteRegister(0x11, 0x7F);
#if CODEC_ALWAYS_AS_MASTER_FTR	
	WriteRegister(0x00, 0xC0);
#else
	WriteRegister(0x00, 0x80);
#endif
//		WriteRegister(0x00, 0x80);
	tls_os_time_delay(HZ/20);
	WriteRegister(0x0D, 0x01);
	WriteRegister(0x01, 0x3F);

	// SET ADC
	WriteRegister(0x14, DADC_GAIN);

	// SET DAC
	WriteRegister(0x12, 0x00);

	// ENABLE HP DRIVE
	WriteRegister(0x13, 0x10);//

	// SET ADC/DAC DATA FORMAT
	WriteRegister(0x09, 0x0C);// right channel to dac
	WriteRegister(0x0A, 0x0C);//
	

	// SET LOW OR NORMAL POWER MODE
	WriteRegister(0x0E, 0x02);
	WriteRegister(0x0F, 0x44);

	// SET ADC
	WriteRegister(0x15, 0x00);
	WriteRegister(0x1B, 0x05);
	WriteRegister(0x1C, 0x65);
	WriteRegister(0x37, 0x08);	
	WriteRegister(0x17, ADC_VOLUME_GAIN);
	WriteRegister(0x32, 0xBF);//  DAC VOL

#if 0
	WriteRegister(0x1C,0x65);//close eq
	WriteRegister(0x1D,0x03);
	WriteRegister(0x1E,0x43);
	WriteRegister(0x1F,0x1F);
	WriteRegister(0x20,0x6C);
	WriteRegister(0x21,0x01);
	WriteRegister(0x22,0x32);
	WriteRegister(0x23,0x9B);
	WriteRegister(0x24,0x4B);
	WriteRegister(0x25,0x29);
	WriteRegister(0x26,0x6D);
	WriteRegister(0x27,0xF9);
	WriteRegister(0x28,0xFF);
	WriteRegister(0x29,0x1F);
	WriteRegister(0x2A,0xF7);
	WriteRegister(0x2B,0xFD);
	WriteRegister(0x2C,0xFF);
	WriteRegister(0x2D,0x22);
	WriteRegister(0x2E,0x4B);
	WriteRegister(0x2F,0x5D);
	WriteRegister(0x30,0x7C);
	WriteRegister(0x1C,0x25);//open eq	
#endif	
}


void CodecMute(u8 ifmute)
{
    printf("mute flag:%d\n", ifmute);
    if(ifmute == 0)
        WriteRegister(0x31, 0x00);
    else if(ifmute == 1)
        WriteRegister(0x31, 0x60);
}

/*0---master, 1---slave*/
void CodecWorkModeSwitch(int mode)
{
#if !CODEC_ALWAYS_AS_MASTER_FTR
	if (mode == 0)
	{
		WriteRegister(0x00, 0xC0);
	}
	else
	{	
		WriteRegister(0x00, 0x80);
	}
#endif	
}

void CodecVolume(int vol)
{
    int vol_temp=0;
    
    if(vol < 100)
    {
        vol_temp = vol * 2 + 1; // -95dB ~ +5dB
        WriteRegister(0x32, vol_temp);
    }
}

void ReadAllRegister(void)
{
    int i = 0;

    for(i = 0; i <= 0x45; i++)
    {
        printf("addr 0x%02x = 0x%02x\n", i, ReadRegister(i));
    }
    
}
static u8 ReadRegister(u16 addr)
{				  
	u8 temp=0;
    
	tls_i2c_write_byte(CODEC_ADDR, 1);   
	tls_i2c_wait_ack(); 
    tls_i2c_write_byte(addr, 0);   
	tls_i2c_wait_ack();	    

	tls_i2c_write_byte(CODEC_ADDR + 1, 1);
	tls_i2c_wait_ack();	 
	temp=tls_i2c_read_byte(0, 1);
    
	return temp;
}

static void WriteRegister(u16 addr, u8 data)
{
	tls_i2c_write_byte(CODEC_ADDR, 1); 
	tls_i2c_wait_ack();	   
	tls_i2c_write_byte(addr, 0);
	tls_i2c_wait_ack(); 	 										  		   
	tls_i2c_write_byte(data, 0); 				   
	tls_i2c_wait_ack();  	   
 	tls_i2c_stop();
	tls_os_time_delay(1);
}


